﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

namespace Jerry
{
    /// <summary>
    /// Bundle信息
    /// </summary>
    [Serializable]
    public class BundleInfo
    {
        /// <summary>
        /// 名称
        /// </summary>
        [SerializeField]
        public string name;
        /// <summary>
        /// 大小
        /// </summary>
        [SerializeField]
        public long size;
        /// <summary>
        /// Hash
        /// </summary>
        [SerializeField]
        public string hash;
        /// <summary>
        /// 分包等级
        /// </summary>
        [SerializeField]
        public int packageLev;

        /// <summary>
        /// 依赖
        /// </summary>
        [SerializeField]
        public List<string> dependencies;

        public BundleInfo() { }

        public BundleInfo(string info)
        {
            string[] arr = JerryUtil.String2TArray<string>(info, ',');
            if (arr == null || arr.Length != 4)
            {
                return;
            }
            name = arr[0];
            hash = arr[1];
            size = JerryUtil.String2TArray<long>(arr[2], ',')[0];
            packageLev = JerryUtil.String2TArray<int>(arr[3], ',')[0];
        }

        /// <summary>
        /// 整理成存档字符串
        /// </summary>
        /// <returns></returns>
        public string ToStr()
        {
            return string.Format("{0},{1},{2},{3}", name, hash, size, packageLev);
        }
    }

    /// <summary>
    /// Bundle信息管理
    /// </summary>
    public class BundleInfoMgr
    {
        /// <summary>
        /// 本地资源版本号，首包不含资源就用这个
        /// </summary>
        [SerializeField]
        public string m_Version = "0.0.0";
        /// <summary>
        /// 当前分包等级
        /// </summary>
        [SerializeField]
        public int m_CurPackageLev = 0;

        /// <summary>
        /// 信息列表
        /// </summary>
        [SerializeField]
        private List<BundleInfo> m_InfoList = new List<BundleInfo>();

        /// <summary>
        /// 信息列表
        /// </summary>
        public List<BundleInfo> InfoList
        {
            get
            {
                return m_InfoList;
            }
            set
            {
                m_InfoList = value;
                isDirty++;
            }
        }
        /// <summary>
        /// 包外地址，用来保存文件
        /// </summary>
        private string m_PersistentDataPath;
        /// <summary>
        /// 版本信息文件名，不带后缀，Resources加载不要后缀
        /// </summary>
        public const string m_VersionFileShortName = "ResVer";
        /// <summary>
        /// 版本信息文件名，带后缀
        /// </summary>
        public const string m_VersionFileName = m_VersionFileShortName + ".json";
        /// <summary>
        /// 是否有未存档数据
        /// </summary>
        private int isDirty = 0;

        public BundleInfoMgr()
        {
            m_Version = Application.version + ".0";
            m_CurPackageLev = 0;
        }

        /// <summary>
        /// 设置包外路径
        /// </summary>
        /// <param name="persistentDataPath"></param>
        public void SetPersistentDataPath(string persistentDataPath)
        {
            m_PersistentDataPath = persistentDataPath;
        }

        /// <summary>
        /// 不存在的将忽略
        /// </summary>
        /// <param name="bundleNames"></param>
        /// <returns></returns>
        public List<BundleInfo> Names2Infos(List<string> bundleNames)
        {
            List<BundleInfo> ret = new List<BundleInfo>();
            BundleInfo tmp = null;
            foreach (string bundle in bundleNames)
            {
                tmp = m_InfoList.Find((x) => x.name.Equals(bundle));
                if (tmp != null)
                {
                    ret.Add(tmp);
                }
            }
            return ret;
        }

        /// <summary>
        /// 下载完才能修改
        /// </summary>
        /// <param name="lev"></param>
        /// <param name="trySave"></param>
        public void ChangePackageLev(int lev, bool trySave = false)
        {
            if (lev > m_CurPackageLev)
            {
                m_CurPackageLev = lev;
                isDirty++;
                if (trySave)
                {
                    SaveData();
                }
            }
        }

        /// <summary>
        /// 修改或增加数据
        /// </summary>
        /// <param name="info"></param>
        public void ChangeOrAddData(BundleInfo info, bool trySave = false)
        {
            if (info == null)
            {
                return;
            }
            BundleInfo old = m_InfoList.Find((x) => x.name.Equals(info.name));
            if (old == null)
            {
                m_InfoList.Add(info);
                isDirty++;
            }
            else
            {
                if (!old.hash.Equals(info.hash)
                    || old.packageLev != info.packageLev)
                {
                    old.hash = info.hash;
                    old.packageLev = info.packageLev;
                    isDirty++;
                }
            }
            if (trySave && isDirty >= 5)
            {
                SaveData();
            }
        }

        /// <summary>
        /// 保存数据
        /// </summary>
        /// <param name="force"></param>
        public void SaveData(bool force = false)
        {
            if (!force && isDirty <= 0)
            {
                return;
            }
            isDirty = 0;
            string pdPath = m_PersistentDataPath + "/" + m_VersionFileName;
            //Add的时候可能会乱序，所以还是排一次
            m_InfoList.Sort((x, y) =>
            {
                if (x.packageLev != y.packageLev)
                {
                    return x.packageLev.CompareTo(y.packageLev);
                }
                return x.name.CompareTo(y.name);
            });
            File.WriteAllText(pdPath, JsonUtility.ToJson(this, false), Encoding.UTF8);
        }
    }
}